package com.bestcem.xm.award.service.impl;

import cn.hutool.core.lang.Validator;
import com.alibaba.fastjson.JSON;
import com.bestcem.xm.award.constant.Constants;
import com.bestcem.xm.award.constant.RequestAwardConstants;
import com.bestcem.xm.award.entity.mongo.BaseEntity;
import com.bestcem.xm.award.entity.pojo.AwardAwardDO;
import com.bestcem.xm.award.entity.pojo.AwardRequestDO;
import com.bestcem.xm.award.enums.AwardTypeEnum;
import com.bestcem.xm.award.service.bo.award.AwardAwardBO;
import com.bestcem.xm.award.service.dto.requestaward.RequestAwardDTO;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.uitls.JsonUtil;
import com.bestcem.xm.common.core.uitls.SignUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import static com.bestcem.xm.award.enums.AwardRequestStatusEnum.CUSTOM_UNDONE;
import static com.bestcem.xm.award.enums.AwardTypeEnum.CUSTOM;

/**
 * 定制相关服务实现
 *
 * @author sh.pei <sh.pei@idiaoyan.com>
 * @version v1.0
 * @date 2021/7/2 15:18
 */
@Slf4j
@Service
public class CustomAwardServiceImpl extends AbstractAwardAwardService {
    /**
     * 第三方接口返回值 状态
     */
    private static final String CODE = "code";

    /**
     * 第三方接口返回值 数据
     */
    private static final String DATA = "data";

    /**
     * 第三方接口返回值 链接
     */
    private static final String REDIRECT_URL = "redirect_url";

    /**
     * http
     */
    private static final String HTTP = "http";

    /**
     * page
     */
    private static final String PAGE = "page";

    @Resource
    private RestTemplate restTemplate;

    @Override
    public AwardTypeEnum getAwardTypeEnum() {
        return AwardTypeEnum.CUSTOM;
    }


    @Override
    public ServiceResult<String> doRequestAward(RequestAwardDTO requestAwardDTO) {
        // 返回结构体
        HashMap<String, Object> customAwardDTO = new HashMap<>();
        customAwardDTO.put("ttype", CUSTOM.getIndex());
        // 奖励id
        String awardId = Optional.ofNullable(requestAwardDTO).map(RequestAwardDTO::getAwardAwardDO)
                .map(BaseEntity::getId).orElse(Constants.BLANK);
        if (StringUtils.isBlank(awardId)) {
            return ServiceResult.fail(RequestAwardConstants.MISSING_AWARD_ID);
        }
        // 奖励信息 返回信息只需要page.template_fp、page.gcss_fp、page.url
        AwardAwardDO awardAwardDO = requestAwardDTO.getAwardAwardDO();
        customAwardDTO.put("page", Optional.ofNullable(awardAwardDO).map(AwardAwardDO::getPage).orElse(null));
        customAwardDTO.put("seq", Optional.ofNullable(requestAwardDTO).map(RequestAwardDTO::getAwardRequestDO)
                .map(AwardRequestDO::getSurvey).map(AwardRequestDO.Survey::getSeq).orElse(null));
        // 待插入AWARD_REQUEST数据
        AwardRequestDO request = Optional.ofNullable(requestAwardDTO).map(RequestAwardDTO::getAwardRequestDO).orElse(null);
        if (Validator.isNull(request)) {
            return ServiceResult.fail(RequestAwardConstants.MISSING_AWARD_REQUEST);
        }
        request.setStatus(CUSTOM_UNDONE.getIndex());
        // 插入AWARD_REQUEST数据
        AwardRequestDO awardRequestDO = awardRequestDao.insert(request);
        String requestId = Optional.ofNullable(awardRequestDO).map(AwardRequestDO::getId).orElse(Constants.BLANK);
        if (StringUtils.isBlank(requestId)) {
            return ServiceResult.fail(RequestAwardConstants.AWARD_REQUEST_SAVE_ERROR);
        }
        customAwardDTO.put("request_id", requestId);
        customAwardDTO.put("survey_custom_params", Optional.ofNullable(requestAwardDTO).map(RequestAwardDTO::getAwardRequestDO)
                .map(AwardRequestDO::getDeliver).orElse(null));
        // 生成签名
        Map<String, Object> map = JsonUtil.convertValueSnake(customAwardDTO, new TypeReference<Map<String, Object>>() {
        });
        String sig = SignUtil.genSign(map, Constants.BLANK);
        customAwardDTO.put("sig", sig);
        // http请求 page.url 获取response.data
        try {
            Map<String, Object> response = this.postRequest(customAwardDTO, Optional.ofNullable(awardAwardDO).map(AwardAwardDO::getPage).map(AwardAwardDO.Page::getUrl).orElse(null));
            if (log.isInfoEnabled()) {
                log.info("[Award] 第三方资源申请返回结果:{}", JSON.toJSONString(response));
            }
            if (Validator.isNull(response) || Integer.parseInt(response.get(CODE).toString()) != Constants.ZERO) {
                log.error("[Award] redirectUrl not fullfill,customAwardDTO:{},response:{}", JSON.toJSONString(customAwardDTO), JSON.toJSONString(response));
                return ServiceResult.fail(Constants.THIRD_PART_REQUEST_ERROR);
            }
            if (Validator.isNotNull(response.get(DATA))) {
                Map<String, Object> data = (Map<String, Object>) response.get(DATA);
                String redirectUrl = Validator.isNotNull(data.get(REDIRECT_URL)) ? String.valueOf(data.get(REDIRECT_URL)) : Constants.BLANK;
                if (StringUtils.isNotBlank(redirectUrl) && !redirectUrl.startsWith(HTTP)) {
                    log.error("[Award] redirectUrl not fullfill,customAwardDTO:{},response:{}", JSON.toJSONString(customAwardDTO), JSON.toJSONString(response));
                    return ServiceResult.fail(Constants.THIRD_PART_REQUEST_ERROR);
                }
                customAwardDTO.putAll(data);

            }
        } catch (Exception e) {
            log.error("[Award] 第三方资源申请失败,customAwardDTO:{}, award_id {}", JSON.toJSONString(customAwardDTO), awardId, e);
            return ServiceResult.fail(Constants.THIRD_PART_REQUEST_ERROR);
        }
        // 不暴露URL给前端
        if (customAwardDTO.get(PAGE) != null && customAwardDTO.get(PAGE) instanceof AwardAwardDO.Page) {
            ((AwardAwardDO.Page) customAwardDTO.get(PAGE)).setUrl(null);
        }
        String data = JsonUtil.transferToJsonSnake(customAwardDTO);
        return ServiceResult.success(data);
    }

    /**
     * post请求 第三方url 返回结果
     *
     * @param customAwardDTO 请求参数
     * @return Map<String, Object> 返回结果
     */
    private Map<String, Object> postRequest(Map<String, Object> customAwardDTO, String url) {
        Map<String, Object> response;
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            MediaType type = MediaType.parseMediaType("application/json;charset=UTF-8");
            httpHeaders.setContentType(type);
            String body = JsonUtil.transferToJsonSnake(customAwardDTO);
            HttpEntity<String> httpEntity = new HttpEntity<>(body, httpHeaders);

            ResponseEntity<String> apiResponse = restTemplate.postForEntity
                    (
                            url,
                            httpEntity,
                            String.class
                    );
            response = JsonUtil.jsonToTransfer(apiResponse.getBody(), new TypeReference<Map<String, Object>>() {
            });
            return response;
        } catch (Exception e) {
            log.error("[Award] 第三方资源申请失败", e);
            return null;
        }
    }

    /**
     * 奖励类型单独检查是否可以更新或修改
     *
     * @param awardAward 奖励数据
     * @return
     */
    @Override
    public ServiceResult<String> independentCheckAward(AwardAwardBO awardAward) {
        Optional<AwardAwardBO> optional = Optional.ofNullable(awardAward);
        if (!optional.map(AwardAwardBO::getPage).map(AwardAwardBO.Page::getUrl).isPresent()) {
            return ServiceResult.fail("定制api为空！");
        }
        awardAward.getPage().setPc(null);
        awardAward.getPage().setMobile(null);
        awardAward.setBasic(null);
        awardAward.setIssue(null);
        awardAward.setAwards(null);
        return ServiceResult.success();
    }
}
